/**
 * 
 */
package com.tvshows.structure.bdd;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import com.tvshows.structure.bdd.repositories.interfaces.FavoriteRepository;
import com.tvshows.structure.bdd.repositories.interfaces.HistoriqueRepository;
import com.tvshows.structure.bdd.repositories.interfaces.PropertyRepository;
import com.tvshows.structure.beans.Favorite;
import com.tvshows.structure.beans.Historique;
import com.tvshows.structure.beans.Property;

/**
 * @author tMidy
 * <p>
 * Class managing queries to the database
 * </p>
 */
public class BddQueries
{

    /**
     * The bddQueries
     */
    private static BddQueries bddQueries;

    /**
     * The logger
     */
    private static final Logger LOGGER = Logger.getLogger( BddQueries.class );

    /**
     * The favorites list
     */
    private List<Favorite> favoritesList;

    /**
     * If the refresh job is running
     */
    private boolean isJobRunning = false;

    private FavoriteRepository favoriteRepository = (FavoriteRepository) ContextLoader.getBean( "favoriteRepository" );

    private PropertyRepository propertyRepository = (PropertyRepository) ContextLoader.getBean( "propertyRepository" );

    private HistoriqueRepository historiqueRepository = (HistoriqueRepository) ContextLoader
        .getBean( "historiqueRepository" );

    /**
     * Constructor of the class
     */
    public BddQueries()
    {

    }

    /**
     * @return the favorites table
     */
    public List<Favorite> loadFavorites()
    {
        if ( favoritesList != null )
        {
            return favoritesList;
        }
        favoritesList = favoriteRepository.loadAllFavorites();
        return favoritesList;
    }

    /**
     * @return the favorites table
     */
    public List<Favorite> loadFavoritesBySchedule()
    {
        return favoriteRepository.loadFavoritesBySchedule();
    }

    /**
     * Adds a favorite
     * 
     * @param nameFavorite the name of the favorite
     * @param seasonNumber The season number
     * @param lastEpisodeNumber the last episode number
     */
    public void addFavorite( String nameFavorite, String seasonNumber, String lastEpisodeNumber, String scheduleFavorite )
    {
        Favorite favorite = new Favorite();
        favorite.setLastEpisodeNumber( lastEpisodeNumber );
        favorite.setNameFavorite( nameFavorite );
        favorite.setSeasonNumber( seasonNumber );
        favorite.setScheduleFavorite( scheduleFavorite );

        favoriteRepository.addFavorite( favorite );

        getFavoritesList().add( favorite );
        sort( favoritesList );
    }

    /**
     * Orders by name the shows
     * 
     * @param favoritesList the list of favorite shows
     */
    private void sort( List<Favorite> favoritesList )
    {
        Collections.sort( favoritesList, new Comparator<Favorite>()
        {
            @Override
            public int compare( Favorite f1, Favorite f2 )
            {
                return f1.getNameFavorite().compareTo( f2.getNameFavorite() );
            }
        } );
    }

    /**
     * Deletes a favorite
     * 
     * @param nameFavorite the favorite to delete
     */
    public void deleteFavorite( String nameFavorite )
    {

        favoriteRepository.deleteFavorite( nameFavorite );
        updateListFavorite( nameFavorite, null, false );
        sort( favoritesList );

    }

    /**
     * Update or delete a favorite from the local list
     * 
     * @param nameFavorite The name of the favorite
     * @param isUpdate is To update?
     * @param favorite the favorite to update
     */
    private void updateListFavorite( String nameFavorite, Favorite favorite, boolean isUpdate )
    {
        for ( Iterator<Favorite> itr = favoritesList.iterator(); itr.hasNext(); )
        {
            Favorite element = itr.next();
            if ( nameFavorite.equals( element.getNameFavorite() ) )
            {
                if ( isUpdate )
                {
                    element.setLastEpisodeNumber( favorite.getLastEpisodeNumber() );
                    element.setNameFavorite( favorite.getNameFavorite() );
                    element.setSeasonNumber( favorite.getSeasonNumber() );
                    element.setScheduleFavorite( favorite.getScheduleFavorite() );
                    break;
                }
                itr.remove();
            }
        }
    }

    /**
     * Updates a favorite show
     */
    public void updateFavorite( String nameFavorite, String seasonNumber, String episodeNumber, String scheduleFavorite )
    {

        Favorite favorite = null;

        favorite = favoriteRepository.findByName( nameFavorite );

        if ( favorite != null )
        {
            favorite.setLastEpisodeNumber( episodeNumber );
            favorite.setNameFavorite( nameFavorite );
            favorite.setSeasonNumber( seasonNumber );
            favorite.setScheduleFavorite( scheduleFavorite );
            favoriteRepository.updateFavorite( favorite );
        }
        // From import
        else
        {
            favorite = new Favorite();
            favorite.setLastEpisodeNumber( episodeNumber );
            favorite.setNameFavorite( nameFavorite );
            favorite.setSeasonNumber( seasonNumber );
            favorite.setScheduleFavorite( scheduleFavorite );
            favoriteRepository.addFavorite( favorite );
        }

        updateListFavorite( nameFavorite, favorite, true );
        sort( favoritesList );
    }

    /**
     * Creates an instance of BddQueries
     * 
     * @return {@link BddQueries} instance
     */
    public static BddQueries getBddQueries()
    {
        if ( bddQueries == null )
        {
            bddQueries = new BddQueries();
        }
        return bddQueries;
    }

    /**
     * Return a favorite show
     * 
     * @param nameFavorite the name of the favorite
     */
    public Favorite loadFavorite( String nameFavorite )
    {
        Favorite favorite = null;
        favorite = favoriteRepository.findByName( nameFavorite );
        // Favorite imported from xml that does not exist in database
        if ( favorite == null )
        {
            int indexFavorite = findFavorite( nameFavorite );
            if ( indexFavorite != -1 )
            {
                favorite = favoritesList.get( indexFavorite );
                addFavorite( nameFavorite, favorite.getSeasonNumber(), favorite.getLastEpisodeNumber(),
                    favorite.getScheduleFavorite() );
                favoritesList.remove( favorite );
            }
        }
        // From xml
        else
        {
            for ( Favorite element : favoritesList )
            {
                if ( nameFavorite.equals( element.getNameFavorite() ) )
                {
                    return element;
                }
            }
        }
        return favorite;
    }

    /**
     * Gets the index of the searched favorite
     * 
     * @param nameFavorite the name of the favorite to search
     * @return the index of the favorite in the list
     */
    private int findFavorite( String nameFavorite )
    {
        for ( Favorite favorite : favoritesList )
        {
            if ( favorite.getNameFavorite().equals( nameFavorite ) )
            {
                return favoritesList.indexOf( favorite );
            }
        }
        return -1;
    }

    /**
     * @return the property path if setted
     */
    public String getPropertyPath()
    {
        Property prop = propertyRepository.getProperty();
        if ( null != prop && !"".equals( prop.getPathProperty() ) )
        {
            return prop.getPathProperty();
        }
        return null;
    }

    /**
     * Updates the property path
     * 
     * @param path the path to set
     */
    public void updatePropertyPath( String path )
    {
        String newPath = path;
        Property prop = propertyRepository.getProperty();

        if ( prop == null )
        {
            prop = new Property();
            if ( newPath == null || newPath.isEmpty() )
            {
                newPath = System.getProperty( "user.dir" ) + "tvshows.properties";
            }
            prop.setPathProperty( newPath );
            propertyRepository.addProperty( prop );
        }
        else
        {
            prop.setPathProperty( path );
            propertyRepository.updateProperty( prop );
        }

    }

    /**
     * @return the favoritesList
     */
    public List<Favorite> getFavoritesList()
    {
        if ( favoritesList == null )
        {
            favoritesList = new ArrayList<Favorite>();
        }
        return favoritesList;
    }

    /**
     * @return the isJobRunning
     */
    public boolean isJobRunning()
    {
        return isJobRunning;
    }

    /**
     * @param isJobRunning the isJobRunning to set
     */
    public void setJobRunning( boolean isJobRunning )
    {
        this.isJobRunning = isJobRunning;
    }

    public boolean hasHistorique( Favorite f )
    {
        LOGGER.debug( "Le show " + f.getNameFavorite() + " a-t-il déjà été ajouté aujourd'hui" );
        return historiqueRepository.findByShow( f ) != null;

    }

    public void addHistorique( Favorite f )

    {
        Historique h = new Historique();
        h.setAddDate( Calendar.getInstance().getTime() );
        h.setFavorite( f );
        historiqueRepository.addHistorique( h );

    }
}
